package com.tul.vapp.servicecenter.embedded;

import java.io.File;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.server.ServerConfig;
import org.apache.zookeeper.server.ZooKeeperServerMain;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tul.cusa.common.exception.SysException;
import com.tul.cusa.common.util.FileUtil;

import javax.annotation.PostConstruct;

/**
 * Created by jyliu on 2017/5/23.
 */
public class EmbeddedZookeeperBean {

	/**
	 * 日志
	 */
	private static final Logger TRACER = LoggerFactory.getLogger(EmbeddedZookeeperBean.class);

	/**
	 * 是否启动
	 */
	private boolean embeddedStart;

	/**
	 * zookeeper端口
	 */
	private String clientPort;

	/**
	 * zookeeper数据目录
	 */
	private String dataDir;

	/**
	 * 单位时间
	 */
	private String tickTime;

	/**
	 * 等待同步时间*tickTime
	 */
	private String initLimit;

	/**
	 * 同步最大时间*tickTime
	 */
	private String syncLimit;

	/**
	 * constructor
	 * 
	 * @param embeddedStart embeddedStart
	 * @param clientPort clientPort
	 * @param dataDir dataDir
	 * @param tickTime tickTime
	 * @param initLimit initLimit
	 * @param  syncLimit syncLimit
	 */
	public EmbeddedZookeeperBean(boolean embeddedStart, String clientPort, String dataDir, String tickTime,
			String initLimit, String syncLimit) {
		this.embeddedStart = embeddedStart;
		this.clientPort = clientPort;
		this.dataDir = dataDir;
		this.tickTime = tickTime;
		this.initLimit = initLimit;
		this.syncLimit = syncLimit;
	}

	/**
	 * constructor
	 */
	public EmbeddedZookeeperBean() {
	}

	/**
	 * 初始化方法
	 * 
	 * @throws SysException 系统异常
	 */
	@PostConstruct
	public void init() throws SysException {
		if (!this.embeddedStart) {
			return;
		}
		Properties props = new Properties();
		props.setProperty("clientPort", this.clientPort);
		String dataDirStr = new File(this.dataDir).getAbsolutePath();

		try {
			if (new File(dataDirStr).exists()) {
				FileUtil.cleanDirectory(new File(dataDirStr));
			} else {
				new File(dataDirStr).mkdirs();
			}
		} catch (IOException e) {
			TRACER.error(e.getMessage(), e);
		}
		props.setProperty("dataDir", dataDirStr);
		props.setProperty("tickTime", tickTime);
		props.setProperty("initLimit", initLimit);
		props.setProperty("syncLimit", syncLimit);

		QuorumPeerConfig quorumConfig = new QuorumPeerConfig();
		try {
			quorumConfig.parseProperties(props);
		} catch (Exception e) {
			TRACER.error(e.getMessage(), e);
			throw new SysException(e);
		}

		final ZooKeeperServerMain zkServer = new ZooKeeperServerMain();
		final ServerConfig config = new ServerConfig();
		config.readFrom(quorumConfig);

		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					zkServer.runFromConfig(config);
				} catch (IOException e) {
					TRACER.error(e.getMessage(), e);
					throw new SysException(e);
				}
			}
		}).start();

		while (true) {
			try {
				TimeUnit.SECONDS.sleep(1);
				ZkClient zkClient = new ZkClient("127.0.0.1:" + clientPort, 10 * 1000);
				zkClient.close();
				System.setProperty("dubbo.application.logger", "slf4j");
				TRACER.info("embedded zookeeper start success。");
				break;
			} catch (Exception e) {
				TRACER.info("embedded zookeeper start failed, try to reconnect...");
			}
		}
	}

	public void setEmbeddedStart(boolean embeddedStart) {
		this.embeddedStart = embeddedStart;
	}

	public void setClientPort(String clientPort) {
		this.clientPort = clientPort;
	}

	public void setDataDir(String dataDir) {
		this.dataDir = dataDir;
	}

	public void setTickTime(String tickTime) {
		this.tickTime = tickTime;
	}

	public void setInitLimit(String initLimit) {
		this.initLimit = initLimit;
	}

	public void setSyncLimit(String syncLimit) {
		this.syncLimit = syncLimit;
	}
}
